/*
 * WS281x.c
 *
 *  Created on: May 10, 2022
 *      Author: Abyss
 */


#include "config.h"

#define NUM (24 + 300)        // Reset 280us / 1.25us = 224
#define WS1 59
#define WS0  29

uint16_t send_Buf[NUM];

//开启led定时器输出
void WS_Load(void)
{
	HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_2, (uint32_t *)send_Buf, NUM);

}

//关闭所有灯
void WS_CloseAll(void)
{
	uint16_t i;
	for (i = 0; i <  24; i++)
		send_Buf[i] = WS0; // 写入逻辑0的占空比
	for (i = 24; i < NUM; i++)
		send_Buf[i] = 0; // 占空比比为0，全为低电平
	WS_Load();
}


//设置单个灯的颜色
uint32_t WS281x_Color(uint8_t red, uint8_t green, uint8_t blue)
{
	return green << 16 | red << 8 | blue;
}

void WS281x_SetPixelColor( uint32_t GRBColor)
{
	uint8_t i;

	for (i = 0; i < 24; ++i)
			send_Buf[24 + i] = (((GRBColor << i) & 0X800000) ? WS1 : WS0);

}

void WS281x_SetRGB(uint8_t rgb[])
{
	uint8_t red, green,  blue;
	uint8_t i;

	red = rgb[0];
	green = rgb[1];
	blue = rgb[2];

	for (i = 0; i < 24; ++i)
			send_Buf[24 + i] = (((WS281x_Color(red, green, blue) << i) & 0X800000) ? WS1 : WS0);
}



//hsv rgb互转
static float min(float a, float b, float c)
{
  float m;
  m = a < b ? a : b;
  return (m < c ? m : c);
}

static float max(float a, float b, float c)
{
  float m;
  m = a > b ? a : b;
  return (m > c ? m : c);
}


void rgb2hsv(uint8_t g, uint8_t r, uint8_t b, float *h, float *s, float *v)
{
  float red, green ,blue;
  float cmax, cmin, delta;

  red =   (float)r / 255;
  green = (float)g / 255;
  blue =  (float)b / 255;

  cmax = max(red, green, blue);
  cmin = min(red, green, blue);
  delta = cmax - cmin;

  /* H */
  if(delta == 0)
  {
    *h = 0;
  }
  else
  {
    if(cmax == red)
    {
      if(green >= blue)
      {
        *h = 60 * ((green - blue) / delta);
      }
      else
      {
        *h = 60 * ((green - blue) / delta) + 360;
      }
    }
    else if(cmax == green)
    {
      *h = 60 * ((blue - red) / delta + 2);
    }
    else if(cmax == blue)
    {
      *h = 60 * ((red - green) / delta + 4);
    }
  }

  /* S */
  if(cmax == 0)
  {
    *s = 0;
  }
  else
  {
    *s = delta / cmax;
  }

  /* V */
  *v = cmax;
}

void hsv2rgb(float h, float s, float v, uint8_t *g, uint8_t *r, uint8_t *b)
{
  if(s == 0)
  {
    *r=*g=*b=v;
  }
  else
  {
    float H = h / 60;
    int hi = (int)H;
    float f = H - hi;
    float p = v * (1 - s);
    float q = v * (1 - f * s);
    float t = v * (1- (1 - f) * s);
    switch (hi){
      case 0:
        *r = (int)(v * 255.0 + 0.5);
        *g = (int)(t * 255.0 + 0.5);
        *b = (int)(p * 255.0 + 0.5);
        break;
      case 1:
        *r = (int)(q * 255.0 + 0.5);
        *g = (int)(v * 255.0 + 0.5);
        *b = (int)(p * 255.0 + 0.5);
        break;
      case 2:
        *r = (int)(p * 255.0 + 0.5);
        *g = (int)(v * 255.0 + 0.5);
        *b = (int)(t * 255.0 + 0.5);
        break;
      case 3:
        *r = (int)(p * 255.0 + 0.5);
        *g = (int)(q * 255.0 + 0.5);
        *b = (int)(v * 255.0 + 0.5);
        break;
      case 4:
        *r = (int)(t * 255.0 + 0.5);
        *g = (int)(p * 255.0 + 0.5);
        *b = (int)(v * 255.0 + 0.5);
        break;
      case 5:
        *r = (int)(v * 255.0 + 0.5);
        *g = (int)(p * 255.0 + 0.5);
        *b = (int)(q * 255.0 + 0.5);
        break;
			default:
				break;
    }
  }
}
